/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aic.lists;

import aic.beans.Customer;
import aic.beans.Item;
import aic.beans.Order;
import aic.misc.DebugPrint;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AvailableItemsList {

    private static List<Item> availableItemsList = Collections.synchronizedList(new LinkedList<Item>());
    private static Lock lock = new ReentrantLock();

    /**
     * This method just adds an item without checking if it is already inserted
     *
     * @param item Item object
     * @return true if the operation was successful
     */
    public static boolean add(Item item) {
        return availableItemsList.add(item);
    }

    /**
     * Prints out a list of all Items within "availableItemsList"
     */
    public static void printList() {
        Iterator it = availableItemsList.iterator();

        while (it.hasNext()) {
            System.out.println(">>list value (availableItemsList): " + it.next());
        }
    }

    /**
     * This method checks if a certain item exists and if it is available in
     * in the needed quantity (quantity is field from Item)
     *
     * @param item Item object
     * @return true if the item is available in the needed quantity
     */
    public static boolean isAvailable(Item item) throws Exception {
        DebugPrint.println("Checking availability for Item: " + item);
        if (availableItemsList.contains(item)) {
            Item availableItem = availableItemsList.get(availableItemsList.indexOf(item));
            if (item.getQuantity() < availableItem.getQuantity()) {
                return true;
            } else {
                return false;
            }
        } else {
            throw new Exception("Item does not exist");
        }
    }

    public static Order placeOrder(Item[] items, Customer customer) throws Exception {

        lock.lock();

        try {

            DebugPrint.println("Checking whether following customer is valid: " + customer);

            // the customer should get checked anyway before this method gets called
            if (CustomerList.contains(customer)) {
                DebugPrint.println("..customer is valid.");
            } else {
                throw new Exception("Customer does not exist");
            }

            DebugPrint.println("Checking availability of all items..");
            for (Item item : items) {
                try {
                    if (!isAvailable(item)) {
                        DebugPrint.println("..item is not available in the required quantity: " + item);
                        throw new Exception("Item is not available");
                    }
                } catch (Exception e) {
                    DebugPrint.println("..item does not exist: " + item);
                    DebugPrint.println("List of existing items: ");
                    throw new Exception("Item does not exist");
                }
            }
            DebugPrint.println("..all items are available! Creating the order..");

            List<Item> itemList = new LinkedList<Item>();
            for (Item item : items) {
                removeQuantity(item);
                ShippingList.add(item);
                itemList.add(item);
            }

            Order order = new Order();
            order.setItems(itemList);

            OrderList.add(order);
            if (CustomerList.add_order(customer, order)) {
                DebugPrint.println("..done! Returning Order item now");
                return order;
            }
            else throw new Exception("Wasn't able to add the order");

        } finally {
            lock.unlock();
        }

    }

    /**
     * This method removes a certain quantity of an item if it is possible
     *
     * @param item Item object
     * @return true if the operation was successful
     */
    private static boolean removeQuantity(Item item) {
        if (availableItemsList.contains(item)) {
            Item availableItem = availableItemsList.get(availableItemsList.indexOf(item));

            if (item.getQuantity() < availableItem.getQuantity()) {
                int newQuantity = availableItem.getQuantity() - item.getQuantity();
                availableItem.setQuantity(newQuantity);
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
